package com.bocaizp.operation.task;

import com.bocaizp.operation.mapper.DataAnalysisMapper;
import com.bocaizp.operation.mapper.UpdateDataMapper;
import com.bocaizp.pojo.DTO.AnalysisHotDTO;
import com.bocaizp.pojo.DTO.AnalysisJobNumberDTO;
import com.bocaizp.pojo.DTO.SalaryDTO;
import com.bocaizp.pojo.DTO.UserValueDTO;
import com.bocaizp.pojo.VO.AdminDataHierarchyMINVO;
import com.bocaizp.pojo.VO.AdminDataHierarchyVO;
import com.bocaizp.pojo.VO.AnalysisNameValueVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.Period;
import java.time.temporal.TemporalAdjusters;
import java.util.LinkedList;
import java.util.List;

/**
 * Author : huang jie
 * Date : 2024/5/6 15:22
 **/
@Component
@Slf4j
public class DataUpdateTask {

	@Autowired
	private UpdateDataMapper updateDataMapper;
	@Autowired
	private DataAnalysisMapper dataAnalysisMapper;

	@Scheduled(cron = "0 0 1 1 * ? ")//每月1号，凌晨1点00分00秒
//	@Scheduled(cron = "40 * * * * ? ")//每十秒
	public void adminData02(){
		log.info("数据更新开始...");
		//更新管理端行业热度与平均薪资数据
		analysisIndustry();
		//更新用户端全国岗位分布数据
		updateCountryJob();
		//更新用户端学历占比数据
		updateDegrees();
		//更新用户端岗位总数数据
		updateJobNumber();
		//更新管理端用户分层数据
		updateUserData();
		log.info("更新完成...");
	}

	/**
	 * 管理端行业数据更新
	 */
	public void analysisIndustry(){
		log.info("更新行业数据...");
		//获取所有行业的列表
		List<String> industry = updateDataMapper.getindsutry();
		for (String in : industry){
			//更新行业热度数据
			int newDataHot = updateDataMapper.getNewHot(in);
			if(newDataHot != 0){
				int newDataAvg = updateDataMapper.getAvgHot(in);
				int newData1 = newDataHot / 1000 + newDataAvg;
				analysisHotAndSalary(in, 0, newData1); // 0 表示行业热度数据
			}
			//更新行业平均薪资数据
			List<SalaryDTO> salaryDTOList = updateDataMapper.getSalary(in);
			if(salaryDTOList != null && !salaryDTOList.isEmpty()){
				int newData2 = salaryAvg(salaryDTOList);
				analysisHotAndSalary(in, 1, newData2);// 1 表示行业平均薪资数据
			}
		}
		log.info("行业数据更新完成");
	}

	/**
	 * 管理端行业数据更新方法
	 */
	public void analysisHotAndSalary(String in, int status, int newdata){

		//使用LinkedList存储更有利于新旧数据更新
		AnalysisHotDTO analysisHotDTO1 = updateDataMapper.getOldHot(in, status);
		LinkedList<Integer> oldData = new LinkedList<>();
		if(analysisHotDTO1 == null){
			return;
		}
		oldData.addLast(analysisHotDTO1.getDateA());
		oldData.addLast(analysisHotDTO1.getDateB());
		oldData.addLast(analysisHotDTO1.getDateC());
		oldData.addLast(analysisHotDTO1.getDateD());
		oldData.addLast(analysisHotDTO1.getDateE());
		oldData.addLast(analysisHotDTO1.getDateF());
		oldData.addLast(analysisHotDTO1.getDateG());
		//删除第一个元素，即删除时间最长的元素，添加新数据
		if(!oldData.isEmpty()){
			oldData.removeFirst();
		}else{
			return;
		}
		//统计新的行业热度值，添加到末尾
		oldData.addLast(newdata);
		//得到y=K*x + c中的c值
		int res = linear(oldData);
		//预测未来四个月
		int cnt = oldData.getLast();
		for ( int i = 1; i < 5; i++){
			oldData.addLast(cnt + res * i);
		}
		//把更新完的数据存入到数据库中，实现持久化存储
		AnalysisHotDTO analysisHotDTO = AnalysisHotDTO.builder()
				.dateA(oldData.get(0))
				.dateB(oldData.get(1))
				.dateC(oldData.get(2))
				.dateD(oldData.get(3))
				.dateE(oldData.get(4))
				.dateF(oldData.get(5))
				.dateG(oldData.get(6))
				.futA(oldData.get(7))
				.futB(oldData.get(8))
				.futC(oldData.get(9))
				.futD(oldData.get(10))
				.industry(in)
				.status(status)
				.build();
		updateDataMapper.updateHot(analysisHotDTO);
	}

	/**
	 * 计算历史数据增长幅度
	 * @param list
	 * @return
	 */
	public int linear(LinkedList<Integer> list){
		//num为所存储数据减一
		int res, num = 6, cnt = list.getFirst(), arr = 0;
		//通过循环计算出以往数据，按月增幅
		for (Integer x : list) {
			//将每个月与上个月的差值加起来
			arr += x - cnt;
			cnt = x;
		}
		res = arr / num;
		//返回计算结果
		return res;
	}

	/**
	 * 计算平均薪资
	 * @param ss
	 * @return
	 */
	public int salaryAvg(List<SalaryDTO> ss){
		double all = 0;
		double num = 0;
		for (SalaryDTO s : ss){
			double res = (double) (s.getSalaryBottom() + s.getSalaryTop()) / 2 * s.getSalaryMonth() / 12;
			all += res;
			num ++;
		}
		return (int) (all / num);
	}

	//-------------------------------------------------------------------------

	/**
	 * 更新用户端全国岗位分布数据
	 */
	public void updateCountryJob(){
		log.info("开始更新用户端全国岗位分布数据...");
		//获取新数据
		List<AnalysisNameValueVO> analysisNameValueVOS = updateDataMapper.getCountryJob();
		//循环更新旧数据
		for(AnalysisNameValueVO an : analysisNameValueVOS){
			updateDataMapper.updateCountryJob(an.getName(),an.getValue());
		}
		log.info("岗位分布数据更新完成");
	}

	/**
	 * 更新用户端岗位学历占比数据
	 */
	public void updateDegrees(){
		log.info("开始更新用户端岗位学历占比数据...");
		//获取新数据
		List<AnalysisNameValueVO> analysisNameValueVOS = updateDataMapper.getDegrees();
		//循环跟新旧数据
		for(AnalysisNameValueVO an : analysisNameValueVOS){
			updateDataMapper.updateDegrees(an.getName(), an.getValue());
		}
		log.info("学历占比数据更新完成");
	}

	/**
	 * 更新岗位总数
	 */
	public void updateJobNumber(){
		log.info("开始更新岗位总数数据");
		int id = 1;
		AnalysisJobNumberDTO number = updateDataMapper.getOldNumber(id);
		int dataNew = updateDataMapper.getNewNumber();

		number.setDataA(number.getDataB());
		number.setDataB(number.getDataC());
		number.setDataC(number.getDataD());
		number.setDataD(number.getDataE());
		number.setDataE(number.getDataF());
		number.setDataF(number.getDataG());
		number.setDataG(number.getDataH());
		number.setDataH(number.getDataI());
		number.setDataI(dataNew);
		number.setId(id);

		updateDataMapper.inserNumber(number);
		log.info("岗位总数数据更新完成");
	}



	/**
	 * 更新用户分层数据
	 * @return
	 */
	public void updateUserData() {
		log.info("用户分层数据更新开始");
		List<UserValueDTO> users = dataAnalysisMapper.getAllUser();
		LocalDate specificDate = LocalDate.of(2024, 4, 1);

		LocalTime specificTime = LocalTime.of(0, 0, 0);

		LocalDateTime localDateTime = LocalDateTime.of(specificDate, specificTime);
		LocalDateTime localDateTime1 = localDateTime.minusDays(30);
		int value1 = 0,value2 = 0,develop1 = 0,develop2 = 0,remain1 = 0,remain2 = 0,detain1 = 0,detain2 = 0;
		for(UserValueDTO user : users){
			if(isHighActive(localDateTime1,user) && isHighFreq(user) && isHighValue(user)){
				value1 ++;
			}
			else if(isHighActive(localDateTime1,user) && isHighFreq(user) && !isHighValue(user)){
				value2 ++;
			}
			else if(isHighActive(localDateTime1,user) && !isHighFreq(user) && isHighValue(user)){
				develop1 ++;
			}
			else if(isHighActive(localDateTime1,user) && !isHighFreq(user) && !isHighValue(user)){
				develop2 ++;
			}
			else if(!isHighActive(localDateTime1,user) && isHighFreq(user) && isHighValue(user)){
				remain1 ++;
			}
			else if(!isHighActive(localDateTime1,user) && isHighFreq(user) && !isHighValue(user)){
				remain2 ++;
			}
			else if(!isHighActive(localDateTime1,user) && !isHighFreq(user) && isHighValue(user)){
				detain1 ++;
			}else{
				detain2 ++;
			}
		}
		AdminDataHierarchyMINVO adminDataHierarchyMINVO = AdminDataHierarchyMINVO.builder()
				.dataOne(value1)
				.dataTwo(value2)
				.dataThree(develop1)
				.dataFour(develop2)
				.dataFive(remain1)
				.dataSix(remain2)
				.dataSeven(detain1)
				.dataEight(detain2)
				.build();
		Long id = updateDataMapper.selectUser();
		adminDataHierarchyMINVO.setId(id);
		updateDataMapper.userStep(adminDataHierarchyMINVO);
		log.info("用户分层数据更新完成");
	}

	public LocalDateTime getMonthOfFirstDay(){
		LocalDateTime now = LocalDateTime.now();
		// 获取本月的第一天
		LocalDateTime firstDayOfMonth = now.with(TemporalAdjusters.firstDayOfMonth());
		// 因为firstDayOfMonth已经是本月的第一天，但时间部分可能是任意的
		LocalDateTime firstDay = firstDayOfMonth.withHour(0).withMinute(0).withSecond(0).withNano(0);
		return firstDay;
	}
	private boolean isHighActive(LocalDateTime L, UserValueDTO user) {
		// 检查用户是否在最近30天内活跃
		return L.isBefore(user.getLastLoginTime());
	}
	private boolean isHighFreq(UserValueDTO user) {
		// 检查用户是否最近三个月登录次数大于或等于10次
		LocalDate startDate = LocalDate.from(user.getCreateTime());
		LocalDate endDate = LocalDate.of(2024, 4, 1);

		// 使用Period类计算两个日期之间的年月日差
		Period period = Period.between(startDate, endDate);

		// 输出结果
		// 注意：Period.getMonths()方法可能会返回负数，如果endDate早于startDate
		// 如果你想要得到非负的月数差，你可能需要做一些额外的计算
		long monthsBetween = period.getYears() * 12L + period.getMonths();
		int res = (int) (monthsBetween / 2);
		if(res != 0){
			return user.getLoginNumber() / res >= 10;
		}
		return false;

	}
	private boolean isHighValue(UserValueDTO user) {
		// 检查用户是否在一定时间内（这里假设是最近三个月，但具体实现可能依赖于你的业务逻辑）收到的面试邀请数量大于或等于8次
		LocalDate startDate = LocalDate.from(user.getCreateTime());
		LocalDate endDate = LocalDate.of(2024, 4, 1);

		// 使用Period类计算两个日期之间的年月日差
		Period period = Period.between(startDate, endDate);

		// 输出结果
		// 注意：Period.getMonths()方法可能会返回负数，如果endDate早于startDate
		// 如果你想要得到非负的月数差，你可能需要做一些额外的计算
		long monthsBetween = period.getYears() * 12L + period.getMonths();
		int res = (int) (monthsBetween / 2);
		if(res != 0){
			return user.getInterviewNumber()/res >= 8;
		}
		return false;

	}


}
